package com.example.androidexample.interpolater;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Interpolator;

import androidx.annotation.Nullable;

public class InterpolatorEffectDisplayView extends View implements ValueAnimator.AnimatorUpdateListener, View.OnClickListener {

    private static final String TAG = "InterpolatorEffectDisplay";

    //计算的坐标原点
    private Point mCoordinateOrigin;
    //坐标轴
    private Paint mAxisPaint;

    //坐标轴箭头高度 和  高度
    private final int mAxisArrowHeight = 20;
    private final int mAxisArrowWidth = 20;

    //文字和坐标点
    private Paint mTextPaint;
    //绘制的文字的相关属性值
    private final int mTextSize = 30;   //px

    private int mTextWidth;
    private int mTextHeight;

    //函数线
    private Paint mFunctionPointPaint;

    //计算的步长总和
    private int mStepMaxValue;

    //计算得到的真实高度/宽度
    private int mRealWidth;
    private int mRealHeight;

    //限制绘制进度标志位
    private int mCurrentProgress = 100;

    //初次加载使用动画的标志位
    private boolean isFirstLoad = true;
    //动画
    private ValueAnimator valueAnimator;
    //设置的要展示的插值器
    private Interpolator interpolator;

    public InterpolatorEffectDisplayView(Context context) {
        super(context);
        init();
    }

    public InterpolatorEffectDisplayView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public InterpolatorEffectDisplayView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        //坐标轴
        mAxisPaint = new Paint();
        mAxisPaint.setStyle(Paint.Style.FILL);
        mAxisPaint.setAntiAlias(true);
        int mAxisStrokeWidth = 5;
        mAxisPaint.setStrokeWidth(mAxisStrokeWidth);
        int mAxisColor = Color.WHITE;
        mAxisPaint.setColor(mAxisColor);

        //文字画笔
        mTextPaint = new Paint();
        mTextPaint.setStyle(Paint.Style.FILL);
        mTextPaint.setAntiAlias(true);
        int mTextColor = Color.WHITE;
        mTextPaint.setColor(mTextColor);
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        //文字的宽高
        String text = "0.0";
        Rect rect = new Rect();
        mTextPaint.getTextBounds(text, 0, text.length(), rect);
        //文本的宽度
        mTextWidth = rect.width();
        //文本的高度
        mTextHeight = rect.height();

        //画函数线的画笔
        mFunctionPointPaint = new Paint();
        mFunctionPointPaint.setStyle(Paint.Style.STROKE);
        mFunctionPointPaint.setAntiAlias(true);
        int mFunctionPointStrokeWidth = 5;
        mFunctionPointPaint.setStrokeWidth(mFunctionPointStrokeWidth);
        int mFunctionPointColor = Color.WHITE;
        mFunctionPointPaint.setColor(mFunctionPointColor);

        initAnim();
        setOnClickListener(this);
    }

    private void initAnim() {
        valueAnimator = ValueAnimator.ofInt(-100, 100);
        valueAnimator.setDuration(2000);
        valueAnimator.addUpdateListener(this);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (isFirstLoad) {
            isFirstLoad = false;
            valueAnimator.start();
        }
    }

    public void setInterpolator(Interpolator interpolator) {
        this.interpolator = interpolator;
        if (!isFirstLoad) {
            if (valueAnimator.isRunning()) {
                valueAnimator.cancel();
            }
            valueAnimator.start();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        int min = Math.min(heightSize, widthSize);
        setMeasuredDimension(MeasureSpec.makeMeasureSpec(min, widthMode), MeasureSpec.makeMeasureSpec(min, heightMode));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //统一宽高
        //整个View的宽高
        int mViewHeight;
        int mViewWidth = mViewHeight = Math.min(w, h);
        //拿到宽高之后 直接设置原点位置
        int mBottomSpacing = 40;
        int mTopSpacing = 40;
        int mRightSpacing = 40;
        //上下左右留白
        int mLeftSpacing = 40;
        mCoordinateOrigin = new Point((mViewWidth - mAxisArrowHeight - mLeftSpacing - mRightSpacing) / 2 + mLeftSpacing,
                (mViewHeight - mAxisArrowHeight - mTopSpacing - mBottomSpacing) / 2 + mAxisArrowHeight + mTopSpacing);

        //绘制坐标轴的长宽
        mRealWidth = mViewWidth - mLeftSpacing - mRightSpacing;
        mRealHeight = mViewHeight - mTopSpacing - mBottomSpacing;

        //拿到宽高之后,可以拿到每一份的步长（按照多少分来分）（需要算上文字的空间  留白的空间）
        //细分值
        int mSubdivisionValue = 100;
        mStepMaxValue = calMaxStepValue(mSubdivisionValue, Math.min(mRealHeight - mAxisArrowHeight,
                mRealWidth - mAxisArrowWidth));
    }

    //计算最大可以绘制的区域
    private int calMaxStepValue(int mSubdivisionValue, int minValue) {
        int targetValue;
        int index = 1;
        while (true) {
            targetValue = mSubdivisionValue * index;
            if (targetValue > minValue) {
                break;
            }
            index++;
        }
        return mSubdivisionValue * (index - 1);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (interpolator == null) {
            return;
        }

        drawLine(canvas);
        drawTextAndPoint(canvas);
        drawPoints(canvas);
    }

    //画坐标轴
    private void drawLine(Canvas canvas) {
        canvas.save();
        canvas.translate(mCoordinateOrigin.x, mCoordinateOrigin.y);
        //draw X
        canvas.drawLine(-(mRealWidth - mAxisArrowHeight) / 2, 0, (mRealWidth - mAxisArrowHeight) / 2 + mAxisArrowHeight, 0, mAxisPaint);
        //draw X arrow
        canvas.drawLine((mRealWidth - mAxisArrowHeight) / 2, (-mAxisArrowWidth / 2), ((mRealWidth - mAxisArrowHeight) / 2 + mAxisArrowHeight), 0, mAxisPaint);
        canvas.drawLine((mRealWidth - mAxisArrowHeight) / 2, (mAxisArrowWidth / 2), ((mRealWidth - mAxisArrowHeight) / 2 + mAxisArrowHeight), 0, mAxisPaint);
        //draw y
        canvas.drawLine(0, (mRealHeight - mAxisArrowHeight) / 2, 0, -((mRealHeight - mAxisArrowHeight) / 2) - mAxisArrowHeight, mAxisPaint);
        //draw y arrow
        canvas.drawLine(-(mAxisArrowWidth / 2), -((mRealHeight - mAxisArrowHeight) / 2), 0, -((mRealHeight - mAxisArrowHeight) / 2) - mAxisArrowHeight, mAxisPaint);
        canvas.drawLine((mAxisArrowWidth / 2), -((mRealHeight - mAxisArrowHeight) / 2), 0, -((mRealHeight - mAxisArrowHeight) / 2) - mAxisArrowHeight, mAxisPaint);
        canvas.restore();
    }

    //绘制坐标点和文字
    private void drawTextAndPoint(Canvas canvas) {
        float stepSize = mStepMaxValue / 20f;
        canvas.save();
        canvas.translate(mCoordinateOrigin.x, mCoordinateOrigin.y);

        //绘制原点
        canvas.drawText("0.0", (-mTextWidth / 2 - 10), (mTextHeight + mTextSize / 2), mTextPaint);
        int mPointRadius = 6;
        canvas.drawCircle(0, 0, mPointRadius, mTextPaint);

        for (int i = -10; i <= 10; i++) {
            if (i == 0) {
                continue;
            }

            //drawX
            if (i % 5 == 0) {
                canvas.drawText("" + i * 1.0f / 10f, stepSize * i, (mTextHeight + mTextSize / 2), mTextPaint);
            }
            canvas.drawCircle(stepSize * i, 0, mPointRadius, mTextPaint);

            //drawY
            if (i % 5 == 0) {
                canvas.drawText("" + i * 1.0f / 10f, -(mTextWidth / 2 - mTextSize / 2), (-(stepSize * i) + (mTextHeight / 2)), mTextPaint);
            }
            canvas.drawCircle(0, (-stepSize * i), mPointRadius, mTextPaint);
        }
        canvas.restore();
    }

    //绘制连线
    private void drawPoints(Canvas canvas) {
        //得到绘制的步长
        float stepSize = mStepMaxValue / 200f;
        Path mPath = new Path();
        canvas.save();
        canvas.translate(mCoordinateOrigin.x, mCoordinateOrigin.y);
        mPath.moveTo(stepSize * -100, interpolator.getInterpolation(-100 * 1.0f / 100f) * -100 * stepSize);
        for (int i = -99; i <= mCurrentProgress; i++) {
            mPath.lineTo(stepSize * i, -interpolator.getInterpolation(i * 1.0f / 100f) * 100 * stepSize);
        }
        canvas.drawPath(mPath, mFunctionPointPaint);
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        mCurrentProgress = (int) animation.getAnimatedValue();
        invalidate();
    }

    @Override
    public void onClick(View v) {
        if (valueAnimator.isRunning()) {
            valueAnimator.cancel();
        }
        valueAnimator.start();
    }
}
